package com.bfsuol.bfsuolframework.core.controller.support;

import com.bfsuol.bfsuolframework.core.utils.DateTimeUtils;
import com.bfsuol.bfsuolframework.core.utils.StringUtils;
import org.apache.log4j.Logger;

import java.util.*;

/**
 * 记录页面传递过来的查询信息，其中key的含义：hql属性名!操作@类型_分组名         <br>
 * 格式：method!operation@type_groupName      <br>
 *                                                          <br>
 * 支持的操作：                                              <br>
 * 	eq = EQUAL(=)——默认，如果没有操作则为等于                 <br>
 * 	lk = LIKE(like '%keyword%')                             <br>
 *  kl= LIKE(like '%keyword')                               <br>
 *  kr= LIKE(like 'keyword%')                               <br>
 * 	gt = GREAT(>)                                           <br>
 * 	lt = LESS(<)                                            <br>
 * 	ge = GREAT_EQUAL(>=)                                    <br>
 *	le = LESS_EQUAL(<=)                                     <br>
 *	nu = IS_NULL(is null)                                   <br>
 *	ne = NOT_EQUAL(!=)                                      <br>
 *	nn = NOT_NULL(is not null)                              <br>
 *                                                          <br>
 *                                                          <br>
 * 支持的类型：                                              <br>
 * s = 字符串string：String ——默认，如果没有类型，则为字符串   <br>
 * b = 逻辑boolean：Boolean                                  <br>
 * i = 整数int：Integer                                      <br>
 * l = 长整数long：Long                                      <br>
 * f = 浮点float：Float                                      <br>
 * d = 双浮点double：Double                                  <br>
 * D = 日期date：Date(格式：yyyy-MM-dd)                      <br>
 * t = 时间datetime：Date(格式：yyyy-MM-dd hh:mm:ss)         <br>
 *                                                          <br>
 *                                                          <br>
 * 如果属性名中包含关联表，需要使用外连接查询，则建立别名，     <br>
 * 名称和别名之间使用“|”分隔，                                <br>
 * 如果使用左连接，则使用“[|”，右连接使用“|]”。               <br>
 * 例如：user.roles|r.id，则r就是user.roles的别名            <br>
 *                                                          <br>
 *                                                          <br>
 * 例如：                                                   <br>
 * user.id!eq@l=1    对应hql is : where user.id = 1        <br>
 * name!eq@s=tom     对应hql is : where name = 'tom'       <br>
 * name!lk@s=tom     对应hql is : where name like '%tom%'  <br>
 *                                                          <br>
 * user.role|r.name!eq@s=admin    对应hql is : from User u where u.role.name = 'admin'         <br>
 * 
 * 
 * @author 曹新龙
 *
 */

public class DefaultQueryParam implements QueryParam{

	private static final Logger logger = Logger.getLogger(DefaultQueryParam.class);
	
	private boolean distinct=false;//是否设置返回结果唯一
	private Map<String,QueryElement> querys = new LinkedHashMap<String,QueryElement>();//
	
	private List<QueryElement> fixed_query;
	private boolean query_changed = false;
	
	public DefaultQueryParam(){}

	public boolean isDistinct() {
		return distinct;
	}

	public DefaultQueryParam setDistinct(boolean distinct) {
		this.distinct = distinct;
		return this;
	}
	
	public DefaultQueryParam clear() {
		querys.clear();
		orders.clear();
		return this;
	}
	
	/*
	 * 查询******************************************************************
	 */
	
	public boolean hasQuerys(){
		return !querys.isEmpty();
	}
	public boolean hasQuery(String key){
		return querys.containsKey(key);
	}
	public DefaultQueryParam removeQuery(String key){
		QueryElement q = querys.remove(key);
		if(q != null){
			query_changed = true;
		}
		return this;
	}
	public DefaultQueryParam clearQuery(){
		querys.clear();
		query_changed = true;
		return this;
	}
	public QueryElement getQuery(String key){
		return querys.get(key);
	}
	public Collection<String> getQueryKeys(){
		return querys.keySet();
	}
	public Collection<QueryElement> getQuerys(){
		return querys.values();
	}
	public Collection<QueryElement> getFixedQuerys(){
		fixQueryList();
		return fixed_query;
	}
	
	
	//整理查询的数据
	private void fixQueryList(){
		if(!query_changed){
			return;
		}
		fixed_query = new LinkedList<QueryElement>();
		boolean no_or_query = true;
		for(QueryElement q : querys.values()){
			//检查是否是or查询，是则将它加入到对应的or组中
			if(q.getGroupName() == null || q.getGroupName().equals("")){
				if(logger.isDebugEnabled()){
					logger.debug("FixQueryList: Add AND Auery! query.key=" + q.getKey());
				}
				fixed_query.add(q);
			}else{
				no_or_query = true;
				for(QueryElement saved_q : fixed_query){
					if(q.getGroupName().equals(saved_q.getGroupName())){
						saved_q.addOrQuerys(q);
						no_or_query = false;
						if(logger.isDebugEnabled()){
							logger.debug("FixQueryList： Add Saved OR Query! query.key=" + q.getKey());
						}
						break;
					}
				}
				if(no_or_query){
					fixed_query.add(q);
					if(logger.isDebugEnabled()){
						logger.debug("FixQueryList: Add OR Query! query.key=" + q.getKey());
					}
				}
			}
		}
		query_changed = false;
	}
	
	public DefaultQueryParam addQuery(String key, String value, boolean is_fore) {
		putQuery(key,value,is_fore);
		return this;
	}
	
	public DefaultQueryParam addQuery(String key, String value) {
		putQuery(key,value);
		return this;
	}
	public DefaultQueryParam addQuery(String key, Integer value) {
		putQuery(key,String.valueOf(value));
		return this;
	}
	public DefaultQueryParam addQuery(String key, Long value) {
		putQuery(key,String.valueOf(value));
		return this;
	}
	public DefaultQueryParam addQuery(String key, Float value) {
		putQuery(key,String.valueOf(value));
		return this;
	}
	public DefaultQueryParam addQuery(String key, Double value) {
		putQuery(key,String.valueOf(value));
		return this;
	}
	public DefaultQueryParam addQuery(String key, Boolean value) {
		putQuery(key,String.valueOf(value));
		return this;
	}
	public DefaultQueryParam addQuery(String key, Date value) {
		return addQuery(key,value, "yyyy-MM-dd");
	}
	public DefaultQueryParam addQuery(String key, Date value, String pattern) {
		putQuery(key,DateTimeUtils.format(value,pattern));
		return this;
	}
	
	private void putQuery(String key,String value){
		putQuery(key,value,false);
	}
	
	private void putQuery(String key,String value,boolean is_fore){
		if(key == null){
			return;
		}
		if(!StringUtils.isBlank(value)){
			value=value.trim();
		}
		QueryElement q = new QueryElement(key,value);
		q.setIsfore(is_fore);
		//检查对应的查询类型是否必须含有value值，没有则不加入
		if(q.getValue() == null && !q.getOperator().equals(OPERATOR.IS_NULL) && !q.getOperator().equals(OPERATOR.NOT_NULL) ){
			if(logger.isDebugEnabled()){
				logger.debug("Abandon Query! query.key=" + q.getKey() + ";query.value=" + q.getValue());
			}
			return;
		}
		querys.put(key,q);
		if(logger.isDebugEnabled()){
			logger.debug("Add Query! query.key=" + q.getKey() + ";query.value=" + q.getValue());
		}
		query_changed = true;
	}
	
	public String getString(String key, String defaultValue){
		QueryElement qe = getQuery(key);
		if(qe==null){
			return defaultValue;
		}
		return qe.getString(defaultValue);
	}
	public Integer getInteger(String key, Integer defaultValue){
		QueryElement qe = getQuery(key);
		if(qe==null){
			return defaultValue;
		}
		return qe.getInteger(defaultValue);
	}
	public Long getLong(String key, Long defaultValue){
		QueryElement qe = getQuery(key);
		if(qe==null){
			return defaultValue;
		}
		return qe.getLong(defaultValue);
	}
	public Float getFloat(String key, Float defaultValue){
		QueryElement qe = getQuery(key);
		if(qe==null){
			return defaultValue;
		}
		return qe.getFloat(defaultValue);
	}
	public Double getDouble(String key, Double defaultValue){
		QueryElement qe = getQuery(key);
		if(qe==null){
			return defaultValue;
		}
		return qe.getDouble(defaultValue);
	}
	public Boolean getBoolean(String key, Boolean defaultValue){
		QueryElement qe = getQuery(key);
		if(qe==null){
			return defaultValue;
		}
		return qe.getBoolean(defaultValue);
	}
	public Date getDate(String key, Date defaultValue){
		return getDate(key,defaultValue,"yyyy-MM-dd");
	}
	public Date getDateTime(String key, Date defaultValue){
		return getDate(key,defaultValue,"yyyy-MM-dd HH:mm:ss");
	}
	public Date getDate(String key, Date defaultValue,String pattern){
		QueryElement qe = getQuery(key);
		if(qe==null){
			return defaultValue;
		}
		return qe.getDate(defaultValue,pattern);
	}
	/**
	 * 排序***************************************************************************************************************
	 */
	
	private Map<String,OrderElement> orders = new LinkedHashMap<String,OrderElement>();//排序字段

	/*
	 * 添加
	 */
	public Collection<OrderElement> getOrders() {
		return orders.values();
	}
	public boolean hasOrder(String order){
		return orders.containsKey(order);
	}
	public boolean hasOrders(){
		return !orders.isEmpty();
	}
	public DefaultQueryParam removeOrder(String key){
		orders.remove(key);
		return this;
	}
	public DefaultQueryParam clearOrder(){
		orders.clear();
		return this;
	}
	
	public QueryParam addOrder(String order){
		if(order != null && !order.trim().equals("")) {
			addOrderElement(new OrderElement(order));
		}
		return this;
		
	}
	public DefaultQueryParam addOrderAsc(String order) {
		return addOrder(order,true);
	}
	public DefaultQueryParam addOrderDesc(String order) {
		return addOrder(order,false);
	}
	public DefaultQueryParam addOrder(String order, boolean isASC){
		if(order != null && !order.trim().equals("")) {
			addOrderElement(new OrderElement(order,isASC));
		}
		return this;
	}
	
	private void addOrderElement(OrderElement element){
		if(orders.containsKey(element.getField())){
			orders.remove(element.getField());
		}
		orders.put(element.getField(),element);
	}

}
